home *** CD-ROM | disk | FTP | other *** search
- Subject: Re: MiNT 1.10 re-sync
- Date: Thu, 9 Jun 94 20:35:06 CDT
- From: Juergen Lock <nox@jelal.north.de>
- In-Reply-To: <9406080703.AA15701@hera.rbi.informatik.uni-frankfurt.de>; from "Kay Roemer" at Jun 8, 94 9:03 am
- Message-Id: <9406091835.AA00187@jelal.north.de>
-
- Kay Roemer writes:
-
- > > Upon reflection, it would probably be easier to load shared text regions at the
- > > top of memory, and continue creating the TPA from lower memory. That way you
- > > don't have to worry about artificially limiting the amount of memory you give
- > > to a newly spawned process. (I wonder how topdown solved this problem...)
- >
- > This sounds like a possible solution.
-
- hmm i don't know, doesn't falcons need free space at top when changing
- screen size (s_realloc)?
-
- > TPA doesn't matter in this case, because
- > it is freed when the process (running a shared text) exits. Fragmentation seems
- > to occur, when
- >
- > 1) running shared text
- > 2) last process running shared text exits, shared text still hangs around.
- > 3) allocating memory in eg, a device driver or fs or running TSR or daemon.
-
- and when MiNT needs a new nalloc arena...
-
- > 4) goto 1
- >
- > After a few iterations the stuff allocated in 3) prevents the free shared
- > text regions from beeing joined together to one large hunk.
- >
- > Sigh! Thats a real problem when physical address space == virtual address
- > space.
-
- yes :-(
- >
- > Kay.
-
- ok here is what i've been testing the last few weeks. works for me
- although there could still be bugs that only show up on 68030, etc.
- but first a few other fixes to add to Michaels collection. :)
-
- 0. this was missing: use new value for TIOCSETP and keep old for
- TIOCSETN, other way around can hang old binaries...
-
- Index: file.h
- @@ -340,7 +341,7 @@
- #define FIONREAD (('F'<< 8) | 1)
- #define FIONWRITE (('F'<< 8) | 2)
- #define TIOCGETP (('T'<< 8) | 0)
- -#define TIOCSETP (('T'<< 8) | 1)
- +#define TIOCSETN (('T'<< 8) | 1)
- #define TIOCGETC (('T'<< 8) | 2)
- #define TIOCSETC (('T'<< 8) | 3)
- #define TIOCGLTC (('T'<< 8) | 4)
- @@ -361,7 +362,7 @@
- #define TIOCGFLAGS (('T'<< 8) | 22)
- #define TIOCSFLAGS (('T'<< 8) | 23)
- #define TIOCOUTQ (('T'<< 8) | 24)
- -#define TIOCSETN (('T'<< 8) | 25)
- +#define TIOCSETP (('T'<< 8) | 25)
-
- /* cursor control Fcntls:
- * NOTE THAT THESE MUST BE TOGETHER
-
- 1. getcwd crashed when called from `unmounted' (Dlock) fs...
-
- Index: unifs.c
- @@ -379,6 +379,10 @@
- return EINTRN;
- }
-
- + if (!fs) {
- + *pathname = 0;
- + return 0;
- + }
- if (!(fs->fsflags & FS_LONGPATH)) {
- r = (*fs->getname)(&curproc->root[dir->dev], dir, tmppath, PATH_MAX);
- if (r) return r;
-
- 2. ls -l /pipe: fix pty modes (S_IFCHR) and 14-char names
-
- Index: pipefs.c
- @@ -477,11 +477,12 @@
- outp->readers = 1; outp->writers = selfread ? 1 : VIRGIN_PIPE;
- outp->wsel = outp->rsel = 0;
- }
- + b->name[NAME_MAX] = '\0';
- strncpy(b->name, name, NAME_MAX);
- b->time = timestamp;
- b->date = datestamp;
- b->dosflags = attrib;
- - b->mode = ((attrib & FA_SYSTEM) ? S_IFCHR : S_IFIFO) | mode;
- + b->mode = ((attrib & FA_SYSTEM) ? S_IFCHR : S_IFIFO) | (mode & ~S_IFMT);
- b->uid = curproc->ruid;
- b->gid = curproc->rgid;
-
- 3. make echo >pipe/pty work when other end already open, only fail if
- O_EXCL or Fcreate attr != 0. (shells often creat() output redirection...)
-
- Index: dosfile.c
- @@ -34,7 +35,7 @@
- unsigned perm;
- int creating;
- char temp1[PATH_MAX];
- - extern FILESYS proc_filesys;
- + extern FILESYS proc_filesys, pipe_filesys;
-
- /* for special BIOS "fake" devices */
- extern DEVDRV fakedev;
- @@ -59,9 +60,12 @@
-
- /*
- * file found: this is an error if (O_CREAT|O_EXCL) are set
- + * ...or if this is Fcreate with nonzero attr on the pipe filesystem
- */
-
- - if ( (r == 0) && ( (rwmode & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL) ) ) {
- + if ( (r == 0) && ( (rwmode & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL) ||
- + (attr && fc.fs == &pipe_filesys &&
- + (rwmode & (O_CREAT|O_TRUNC)) == (O_CREAT|O_TRUNC)))) {
- DEBUG(("do_open(%s): file already exists",name));
- mint_errno = EACCDN;
- release_cookie(&fc);
- Index: pipefs.c
- @@ -544,10 +545,12 @@
- }
- p->flags &= ~O_HEAD;
- } else {
- +#if 0
- if (f->flags & O_TRUNC) {
- DEBUG(("pipe_open: fifo already exists"));
- return EACCDN;
- }
- +#endif
- }
- /*
- * check for file sharing compatibility. note that O_COMPAT gets mutated
-
- 4. save a long read
-
- Index: intr.spp
- @@ -42,7 +42,7 @@
- _mint_5ms:
- move.l a0,-(sp)
- lea _uptimetick,a0
- - tst.l _uptimetick
- + tst.l (a0)
- bne.s L_no_uptime
- move.l #200,(a0)
- L_no_uptime:
-
- 5. fork() doesn't copy shared text regions so why allocate memory
- to save them :)
-
- Index: dosmem.c
- @@ -1283,6 +1294,15 @@
- if (save) {
- TRACE(("do_vfork: saving parent"));
- savesize = memused(curproc) - txtsize;
- + if (!txtsize && (p->base->p_flags & F_SHTEXT)) {
- + for (i = 0; i < curproc->num_reg; i++) {
- + m = curproc->mem[i];
- + if (m && (m->mflags & M_SHTEXT)) {
- + savesize -= m->len;
- + break;
- + }
- + }
- + }
- assert(savesize >= 0);
-
- saveplace = (char *)alloc_region(alt, savesize, PROT_P);
-
- 6. and now the sticky text/fragmentation megapatch... does a few things:
-
- . if F_ALTLOAD|F_SHTEXT look at F_MINALT bits to see how much memory
- the new process needs and free sticky text regions if necessary, all
- F_MINALT bits set (0xf0000000) means `as much as you can get'
- . execv..() frees the old process memory before allocating the new ones,
- and so no longer leaves holes in your memory map. this took a few
- ugly hacks but i think its worth it :) the only visible change should
- be when exec'ing a damaged binary the process gets killed, fixing that
- would require reading executables twice.
- . check the sticky bit, just making everything sharable sticky still got
- me too much `out of memory's... and free sticky text regions after disk
- changes or if open() would otherwise fail.
- . also free no more sticky text regions then necessary in alloc, and
- some other small changes.
-
- oh and if you need something to adjust the F_MINALT bits...
-
- #! /usr/bin/perl
- # xsetf [-xhex] files ... -- print/set executable flags
- #
- $aexec = 's L L L L L L S';
- # short a_magic; /* magic number */
- #unsigned long a_text; /* size of text segment */
- #unsigned long a_data; /* size of initialized data */
- #unsigned long a_bss; /* size of uninitialized data */
- #unsigned long a_syms; /* size of symbol table */
- #unsigned long a_AZero1; /* always zero */
- #unsigned long a_ldflgs; /* program load flags */
- #unsigned short a_isreloc; /* is reloc info present */
-
- while ($_ = $ARGV[0], /^-/) {
- shift;
- last if /^--$/;
- if (/^-x(.*)/) {
- if ($1) {
- $x = $1;
- } else {
- $x = shift;
- next;
- }
- }
- }
- foreach (@ARGV) {
- print $_, ":\t";
- open (F, "+< $_") || die "Can't open";
- sysread (F, $head, length (pack ($aexec, 0))) || die "Can't read header";
- ($a_magic, $a_text, $a_data, $a_bss, $a_syms,
- $a_AZero1, $a_ldflgs, $a_isreloc) = unpack ($aexec, $head);
- die "not executable/corrupted header" unless $a_magic == 0x601a;
- seek (F, 0, 0) || die "Can't seek back";
- print "\n text ", $a_text, " data ", $a_data, " bss ", $a_bss, " symbols ",
- $a_syms, " zero1 ", $a_AZero1, " isreloc ", $a_isreloc, "\n";
- printf "\tldflags\t\t0x%08lx\n", $a_ldflgs;
-
- printf "\t &fload\t\t0x%08lx\n", 1 if ($a_ldflgs&1);
- printf "\t &altload\t0x%08lx\n", 2 if ($a_ldflgs&2);
- printf "\t &altalloc\t0x%08lx\n",4 if ($a_ldflgs&4);
- printf "\t &prot_p\t0x%08lx = 0x%08lx\n", 0xf0, 0
- if (!($a_ldflgs&0xf0));
- printf "\t &prot_g\t0x%08lx = 0x%08lx\n", 0xf0, 0x10
- if (($a_ldflgs&0xf0) == 0x10);
- printf "\t &prot_s\t0x%08lx = 0x%08lx\n", 0xf0, 0x20
- if (($a_ldflgs&0xf0) == 0x20);
- printf "\t &prot_pr\t0x%08lx = 0x%08lx\n", 0xf0, 0x30
- if (($a_ldflgs&0xf0) == 0x30);
- printf "\t &prot_i\t0x%08lx = 0x%08lx\n", 0xf0, 0x40
- if (($a_ldflgs&0xf0) == 0x40);
- printf "\t &prot_??\t0x%08lx = 0x%08lx\n", 0xf0, $a_ldflgs&0xf0
- if (($a_ldflgs&0xf0) > 0x40);
- printf "\t &shtext\t0x%08lx\n", 0x800 if ($a_ldflgs&0x800);
- printf "\t &minalt\t0x%08lx = 0x%08lx\n", 0xf0000000,
- $a_ldflgs&0xf0000000 if ($a_ldflgs&0xf0000802);
- if (defined ($x)) {
- $x = oct ($x) if $x =~ /^0/;
- $a_ldflgs = $x;
- }
- $newhead = pack ($aexec, $a_magic, $a_text, $a_data, $a_bss, $a_syms,
- $a_AZero1, $a_ldflgs, $a_isreloc);
- if ($newhead ne $head) {
- syswrite (F, $newhead, length ($newhead)) == length ($newhead)
- || die "Can't write back header";
- }
- close F || die "Can't close";
- }
- -------cut----
-
- the sticky bit is of course chmod +t. (if your /bin/sh still is on
- GEMDOS change it now... :) and then see you no longer need _shell_p.)
-
- Index: dosfile.c
- @@ -9,6 +9,7 @@
- #include "mint.h"
-
- extern char vt52xkey[];
- +MEMREGION *tofreed; /* to-be-freed shared text region (set in denyshare) */
-
- static long do_dup P_((int,int));
- static void unselectme P_((PROC *));
- @@ -232,6 +236,12 @@
- dispose_fileptr(f);
- return NULL;
- }
- +
- + if (tofreed) {
- + tofreed->links = 0;
- + free_region(tofreed);
- + tofreed = 0;
- + }
-
- /* special code for opening a tty */
- if (is_terminal(f)) {
- Index: dosmem.c
- @@ -53,7 +53,7 @@
- long maxsize, mleft;
-
- if (size == -1L) {
- - maxsize = max_rsize(map);
- + maxsize = max_rsize(map, 0L);
- if (curproc->maxmem) {
- mleft = curproc->maxmem - memused(curproc);
- if (maxsize > mleft)
- @@ -420,6 +420,33 @@
- }
- }
-
- +/* make a local copy of the name, in case we are overlaying the current
- + * process
- + */
- + if (mkname) {
- + lastslash = 0;
- + newname = ptr1;
- + while (*newname) {
- + if (*newname == '\\' || *newname == '/')
- + lastslash = newname;
- + ++newname;
- + }
- + if (!lastslash)
- + lastslash = ptr1;
- + else
- + lastslash++;
- +
- + i = 0; newname = localname;
- + while (i++ < PNAMSIZ) {
- + if (*lastslash == '.' || *lastslash == 0) {
- + *newname = 0; break;
- + }
- + else
- + *newname++ = *lastslash++;
- + }
- + *newname = 0;
- + }
- +
- TRACE(("creating environment"));
-
- if (mkload || mkbase) {
- @@ -434,7 +461,7 @@
- TRACE(("creating base page"));
-
- if (mkbase) {
- - base = create_base((char *)ptr2, env, flags, 0L);
- + base = create_base((char *)ptr2, env, flags, 0L, 0L, 0L, 0L, 0L, 0L);
- if (!base) {
- DEBUG(("Pexec: unable to create basepage"));
- detach_region(curproc, env);
- @@ -444,8 +471,19 @@
- TRACELOW(("Pexec: basepage region(%lx) is %ld bytes at %lx", base, base->len, base->loc));
- }
- else if (mkload) {
- - base = load_region((char *)ptr1, env, (char *)ptr2,
- - &xattr, &text, &flags);
- + char cbuf[128], *tail = ptr2;
- + if (overlay) {
- + static char fbuf[PATH_MAX];
- + ptr1 = strncpy (fbuf, ptr1, PATH_MAX-2);
- + tail = strncpy (cbuf, ptr2, 127);
- + }
- +#if 0
- + base = load_region((char *)ptr1, env, (char *)tail,
- + &xattr, &text, &flags, 0);
- +#else
- + base = load_region((char *)ptr1, env, (char *)tail,
- + &xattr, &text, &flags, overlay);
- +#endif
- if (!base) {
- DEBUG(("Pexec: load_region failed"));
- detach_region(curproc, env);
- @@ -480,33 +518,6 @@
- #endif
- }
-
- -/* make a local copy of the name, in case we are overlaying the current
- - * process
- - */
- - if (mkname) {
- - lastslash = 0;
- - newname = ptr1;
- - while (*newname) {
- - if (*newname == '\\' || *newname == '/')
- - lastslash = newname;
- - ++newname;
- - }
- - if (!lastslash)
- - lastslash = ptr1;
- - else
- - lastslash++;
- -
- - i = 0; newname = localname;
- - while (i++ < PNAMSIZ) {
- - if (*lastslash == '.' || *lastslash == 0) {
- - *newname = 0; break;
- - }
- - else
- - *newname++ = *lastslash++;
- - }
- - *newname = 0;
- - }
- -
- if (mkload || mkbase) {
- /*
- * Now that the file's loaded, flags is set to the prgflags
- @@ -846,7 +857,7 @@
- memory runs low. Assume that we will never have 65535 processes
- using a particular memory region. */
- if (m->links == 0) {
- - if (m->mflags & M_SHTEXT)
- + if (m->mflags & M_SHTEXT_T)
- m->links = 0xffff;
- else
- free_region(m);
- @@ -1307,9 +1327,10 @@
- }
- savemem = addr2mem((virtaddr)saveplace);
- assert(savemem);
- + savemem->mflags |= M_FSAVED;
- for (i = 0; i < curproc->num_reg; i++) {
- m = curproc->mem[i];
- - if (m && m != savemem && !(m->mflags & M_SHTEXT)) {
- + if (m && !(m->mflags & (M_FSAVED|M_SHTEXT))) {
- if (i != 1 || txtsize == 0) {
- quickmove(saveplace, (char *)m->loc, m->len);
- saveplace += m->len;
- @@ -1354,23 +1375,7 @@
- TRACE(("do_vfork: parent waking up"));
-
- if (save) {
- - TRACE(("do_vfork: parent restoring memory"));
- - saveplace = (char *)savemem->loc;
- - for (i = 0; i < curproc->num_reg; i++) {
- - m = curproc->mem[i];
- - if (m && (m != savemem) && !(m->mflags & M_SHTEXT)) {
- - if (i != 1 || txtsize == 0) {
- - quickmove((char *)m->loc, saveplace, m->len);
- - saveplace += m->len;
- - }
- - else {
- - quickmove((char *)m->loc+txtsize, saveplace,
- - m->len - txtsize);
- - saveplace += m->len - txtsize;
- - }
- - }
- - }
- - detach_region(curproc, savemem);
- + fork_restore(curproc, 0L);
- }
- curproc->sigmask = sigmask;
- /* note that the PROC structure pointed to by p may be freed during
- @@ -1380,6 +1385,50 @@
- check_sigs(); /* did we get any signals while sleeping? */
- return newpid;
- }
- +
- +/*
- + * fork_restore(p): restore process memory after a blocking fork
- + */
- +
- +void fork_restore(p, savemem)
- +PROC *p;
- +MEMREGION *savemem;
- +{
- + MEMREGION *m;
- + long txtsize = p->txtsize;
- + char *saveplace;
- + int i;
- +
- + if (!savemem) {
- + for (i = 0; i < p->num_reg; i++) {
- + m = p->mem[i];
- + if (m && (m->mflags & M_FSAVED)) {
- + savemem = m;
- + break;
- + }
- + }
- + if (!savemem)
- + return;
- + }
- + saveplace = (char *)savemem->loc;
- +
- + TRACE(("do_vfork: parent restoring memory"));
- + for (i = 0; i < p->num_reg; i++) {
- + m = p->mem[i];
- + if (m && !(m->mflags & (M_FSAVED|M_SHTEXT))) {
- + if (i != 1 || txtsize == 0) {
- + quickmove((char *)m->loc, saveplace, m->len);
- + saveplace += m->len;
- + }
- + else {
- + quickmove((char *)m->loc+txtsize, saveplace,
- + m->len - txtsize);
- + saveplace += m->len - txtsize;
- + }
- + }
- + }
- + detach_region(p, savemem);
- +}
-
- /*
- * here are the interfaces that the user sees. Pvfork() doesn't save
- Index: filesys.c
- @@ -367,7 +367,7 @@
- int i;
- FILEPTR *f;
- FILESYS *fs;
- - SHTEXT *stext;
- + SHTEXT *stext, **old;
- extern SHTEXT *text_reg; /* in mem.c */
- DIR *dirh;
- fcookie dir;
- @@ -461,13 +461,25 @@
- }
-
- /* free any file descriptors associated with shared text regions */
- - for (stext = text_reg; stext; stext = stext->next) {
- + for (old = &text_reg; (stext = *old);) {
- f = stext->f;
- if (f->fc.dev == d) {
- f->dev = NULL;
- do_pclose(rootproc, f);
- stext->f = 0;
- +/* free region if unattached */
- + if (stext->text->links == 0xffff) {
- + stext->text->links = 0;
- + stext->text->mflags &= ~(M_SHTEXT|M_SHTEXT_T);
- + free_region(stext->text);
- + *old = stext->next;
- + kfree(stext);
- + continue;
- + }
- +/* else clear `sticky bit' */
- + stext->text->mflags &= ~M_SHTEXT_T;
- }
- + old = &stext->next;
- }
- }
-
- @@ -979,6 +991,8 @@
- {
- int newrm, newsm; /* new read and sharing mode */
- int oldrm, oldsm; /* read and sharing mode of already opened file */
- + extern MEMREGION *tofreed;
- + MEMREGION *m = tofreed;
- int i;
-
- newrm = f->flags & O_RWMODE;
- @@ -999,6 +1013,12 @@
- oldsm = list->flags & O_SHMODE;
- if (oldsm == O_DENYW || oldsm == O_DENYRW) {
- if (newrm != O_RDONLY) {
- +/* conflict because of unattached shared text region? */
- + if (!m && (m = find_text_seg(list))) {
- + if (m->links == 0xffff)
- + continue;
- + m = 0;
- + }
- DEBUG(("write access denied"));
- return 1;
- }
- @@ -1040,6 +1060,9 @@
- ; /* everything is OK */
- }
- }
- +/* cannot close shared text regions file here... have open do it. */
- + if (m)
- + tofreed = m;
- return 0;
- }
-
- Index: mem.c
- @@ -576,7 +576,7 @@
- ulong size;
- int mode;
- {
- - MEMREGION *m, *n, *s;
- + MEMREGION *m, *n, *nlast, *nfirstp, *s;
-
- TRACELOW(("get_region(%s,%lx,%x)",
- (map == ker ? "ker" : (map == core ? "core" : "alt")),
- @@ -601,10 +601,12 @@
- /* We come back and try again if we found and freed any unattached shared
- * text regions.
- */
- + nfirstp = NULL;
- retry:
- - s = NULL;
- -
- n = *map;
- +retry2:
- + s = nlast = NULL;
- +
- while (n) {
- if (ISFREE(n)) {
- if (n->len == size) {
- @@ -628,10 +630,13 @@
- return 0;
- }
- }
- + nlast = n;
- /* If this is an unattached shared text region, leave it as a last resort */
- } else if (n->links == 0xffff && (n->mflags & M_SHTEXT)) {
- - if (!s)
- + if (!s) {
- s = n;
- + nfirstp = nlast;
- + }
- }
- n = n->next;
- }
- @@ -639,11 +644,60 @@
- /* Looks like we're out of free memory. Try freeing an unattached shared text
- * region, and then try again to fill this request.
- */
- +#if 1
- + if (s && s->len < size) {
- + long lastsize = 0, end = 0;
- +
- + n = nlast = nfirstp;
- + if (!n || n->next != s)
- + n = s;
- + for (; n; n = n->next) {
- + if (ISFREE(n)) {
- + if (end == n->loc) {
- + lastsize += n->len;
- + } else {
- + s = NULL;
- + nfirstp = nlast;
- + lastsize = n->len;
- + }
- + nlast = n;
- + end = n->loc + n->len;
- + if (lastsize >= size) {
- + break;
- + }
- + } else if (n->links == 0xffff && (n->mflags & M_SHTEXT)) {
- + if (end == n->loc) {
- + if (!s)
- + s = n;
- + lastsize += n->len;
- + } else {
- + s = n;
- + nfirstp = nlast;
- + lastsize = n->len;
- + }
- + end = n->loc + n->len;
- + if (lastsize >= size) {
- + break;
- + }
- + }
- + }
- + if (!n)
- + s = NULL;
- + }
- + if (s) {
- + s->links = 0;
- + free_region(s);
- + if (!(n = nfirstp))
- + n = *map;
- + goto retry2;
- + }
- +#else
- if (s) {
- s->links = 0;
- free_region(s);
- goto retry;
- }
- +#endif
-
- if (m)
- dispose_region(m);
- @@ -836,6 +890,7 @@
- return 0;
- }
-
- +#if 0
- /*
- * max_rsize(map): return the length of the biggest free region
- * in the given memory map, or 0 if no regions remain.
- @@ -879,6 +934,84 @@
- }
- return size;
- }
- +#else
- +/*
- + * max_rsize(map, needed): return the length of the biggest free region
- + * in the given memory map, or 0 if no regions remain.
- + * needed is minimun amount needed, if != 0 try to keep unattached
- + * shared text regions, else count them all as free.
- + */
- +
- +long
- +max_rsize(map, needed)
- + MMAP map;
- + long needed;
- +{
- + MEMREGION *m;
- + long size = 0, lastsize = 0, end = 0;
- +
- + if (needed) {
- + for (m = *map; m; m = m->next) {
- + if (ISFREE(m) ||
- + (m->links == 0xfffe && !(m->mflags & M_SHTEXT))) {
- + if (end == m->loc) {
- + lastsize += m->len;
- + } else {
- + lastsize = m->len;
- + }
- + end = m->loc + m->len;
- + if (lastsize > size) {
- + size = lastsize;
- + }
- + }
- + }
- + if (size >= needed)
- + return size;
- +
- + lastsize = end = 0;
- + }
- + for (m = *map; m; m = m->next) {
- + if (ISFREE(m) || m->links == 0xfffe ||
- + (m->links == 0xffff && (m->mflags & M_SHTEXT))) {
- + if (end == m->loc) {
- + lastsize += m->len;
- + } else {
- + lastsize = m->len;
- + }
- + end = m->loc + m->len;
- + if (lastsize > size) {
- + if (needed && lastsize >= needed)
- + return lastsize;
- + size = lastsize;
- + }
- + }
- + }
- + return size;
- +}
- +
- +/*
- + * tot_rsize(map, flag): if flag == 1, return the total number of bytes in
- + * the given memory map; if flag == 0, return only the number of free
- + * bytes
- + */
- +
- +long
- +tot_rsize(map, flag)
- + MMAP map;
- + int flag;
- +{
- + MEMREGION *m;
- + long size = 0;
- +
- + for (m = *map; m; m = m->next) {
- + if (flag || ISFREE(m) ||
- + (m->links == 0xffff && (m->mflags & M_SHTEXT))) {
- + size += m->len;
- + }
- + }
- + return size;
- +}
- +#endif
-
- /*
- * alloc_region(MMAP map, ulong size, int mode): allocate a new region and
- @@ -979,61 +1112,195 @@
- return m;
- }
-
- +static void terminateme(code)
- + int code;
- +{
- + Pterm (code);
- +}
- +
- MEMREGION *
- -create_base(cmd, env, flags, prgsize)
- +create_base(cmd, env, flags, prgsize, execproc, s, f, fh, xp)
- const char *cmd;
- MEMREGION *env;
- ulong flags, prgsize;
- + PROC *execproc;
- + SHTEXT *s;
- + FILEPTR *f;
- + FILEHEAD *fh;
- + XATTR *xp;
- {
- - long len, coresize, altsize;
- + long len = 0, minalt = 0, coresize, altsize;
- MMAP map;
- - MEMREGION *m;
- + MEMREGION *m, *savemem = 0;
- BASEPAGE *b;
- + PROC *parent = 0; /* keep compiler happy... */
- short protmode;
- + int i;
- +
- +/* if we're about to do an exec tell max_rsize which of the exec'ing
- + process regions will be freed, but don't free them yet so the process
- + can still get an ENOMEM...
- +*/
- + if (execproc) {
- + for (i = 0; i < execproc->num_reg; i++) {
- + m = execproc->mem[i];
- + if (m && m->links == 1)
- + m->links = 0xfffe;
- + }
- +
- +/* if parents mem saved because of a blocking fork that can be restored too
- +*/
- + if ((parent = pid2proc(execproc->ppid)) &&
- + parent->wait_q == WAIT_Q &&
- + parent->wait_cond == (long)execproc) {
- + for (i = 0; i < parent->num_reg; i++) {
- + m = parent->mem[i];
- + if (m && (m->mflags & M_FSAVED)) {
- + m->links = 0xfffe;
- + savemem = m;
- + break;
- + }
- + }
- + }
- + }
-
- /* if flags & F_ALTLOAD == 1, then we might decide to load in alternate
- RAM if enough is available. "enough" is: if more alt ram than ST ram,
- load there; otherwise, if more than (minalt+1)*128K alt ram available
- for heap space, load in alt ram ("minalt" is the high byte of flags)
- */
- + if (flags & (F_ALTLOAD|F_SHTEXT)) {
- + minalt = (flags & F_MINALT) >> 28L;
- + minalt = len = (minalt+1)*128*1024L + prgsize + 256;
- + if ((flags & F_MINALT) == F_MINALT)
- + len = 0;
- + }
- if (flags & F_ALTLOAD) {
- - coresize = max_rsize(core);
- - altsize = max_rsize(alt);
- - if (altsize >= coresize)
- + coresize = max_rsize(core, len);
- + altsize = max_rsize(alt, len);
- + if (altsize >= coresize) {
- map = alt;
- - else {
- - len = (flags & F_MINALT) >> 28L;
- - len = (len+1)*128*1024L + prgsize + 256;
- - if (altsize >= len)
- + len = altsize;
- + } else {
- + if (altsize >= minalt) {
- map = alt;
- - else
- + len = altsize;
- + } else {
- map = core;
- + len = coresize;
- + }
- }
- }
- else
- - map = core;
- + len = max_rsize((map = core), len);
-
- - len = max_rsize(map);
- + if (savemem)
- + savemem->links = 1;
- if (curproc->maxmem && len > curproc->maxmem) {
- len = curproc->maxmem;
- }
-
- - if (len < prgsize) {
- - /* can't possibly load this file in its eligible regions */
- - DEBUG(("create_base: max_rsize smaller than prgsize"));
- - return 0;
- - }
- -
- /* make sure that a little bit of memory is left over */
- if (len > 2*KEEP_MEM) {
- len -= KEEP_MEM;
- }
- -
- + if (s && !s->text &&
- + (!(flags & F_ALTLOAD) || map == alt || altsize < fh->ftext ||
- + !(s->text = addr2mem(alloc_region(alt, fh->ftext, PROT_P))))) {
- + if (len > fh->ftext + KERNEL_MEM)
- + len -= fh->ftext + KERNEL_MEM;
- + else
- + len = 0;
- + }
- +
- + if (prgsize && len < prgsize + 0x400) {
- + /* can't possibly load this file in its eligible regions */
- + DEBUG(("create_base: max_rsize smaller than prgsize"));
- +
- + if (execproc) {
- +/* error, undo the above */
- + for (i = 0; i < execproc->num_reg; i++) {
- + m = execproc->mem[i];
- + if (m && m->links == 0xfffe)
- + m->links = 1;
- + }
- + }
- + if (s && !s->text) {
- + kfree (s);
- + }
- + mint_errno = ENSMEM;
- + return 0;
- + }
- + if (execproc) {
- +/* free exec'ing process memory... if the exec returns after this make it
- + _exit (SIGKILL << 8);
- +*/
- + *((short *) (execproc->stack + ISTKSIZE + sizeof (void (*)()))) =
- + (SIGKILL << 8);
- + execproc->ctxt[SYSCALL].term_vec = (long)rts;
- + execproc->ctxt[SYSCALL].pc = (long)terminateme;
- + execproc->ctxt[SYSCALL].sr |= 0x2000;
- + execproc->ctxt[SYSCALL].ssp = (long)(execproc->stack + ISTKSIZE);
- +
- + if (savemem)
- + fork_restore(parent, savemem);
- + for (i = 0; i < execproc->num_reg; i++) {
- + m = execproc->mem[i];
- + if (m && m->links == 0xfffe) {
- + if (m->mflags & M_SHTEXT_T) {
- + m->links = 0xffff;
- + } else {
- + m->links = 0;
- + free_region(m);
- + }
- + execproc->mem[i] = 0;
- + execproc->addr[i] = 0;
- + }
- + }
- + }
- protmode = (flags & F_PROTMODE) >> F_PROTSHIFT;
-
- - m = addr2mem(alloc_region(map, len, protmode));
- + m = 0;
- + if (s && !s->f) {
- + if (!s->text) {
- + m = addr2mem(alloc_region(map, len + fh->ftext + KERNEL_MEM, protmode));
- + if (!m ||
- + (((len > minalt &&
- + ((flags & F_MINALT) < F_MINALT) &&
- + max_rsize (map, -1) < fh->ftext) ||
- + !(s->text = addr2mem(alloc_region(map, fh->ftext, PROT_P))) ||
- + (m->next == s->text &&
- + !(detach_region (curproc, s->text), s->text = 0))) &&
- + shrink_region(m, fh->ftext))) {
- + if (m)
- + detach_region(curproc, m);
- + kfree (s);
- + mint_errno = ENSMEM;
- + return 0;
- + }
- + if (!s->text) {
- + s->text = m;
- + if (protmode != PROT_P)
- + change_prot_status (curproc, m->loc, PROT_P);
- + m = 0;
- + }
- + }
- + s = get_text_seg(f, fh, xp, s, 0);
- + if (!s) {
- + if (m)
- + detach_region(curproc, m);
- + DEBUG(("create_base: unable to load shared text segment"));
- +/* mint_errno set in get_text_seg */
- + return 0;
- + }
- + }
- +
- + if (!m) {
- + m = addr2mem(alloc_region(map, len, protmode));
- + }
- if (!m) {
- DEBUG(("create_base: alloc_region failed"));
- + mint_errno = ENSMEM;
- return 0;
- }
- b = (BASEPAGE *)(m->loc);
- @@ -1062,7 +1329,7 @@
- */
-
- MEMREGION *
- -load_region(filename, env, cmdlin, xp, text, fp)
- +load_region(filename, env, cmdlin, xp, text, fp, isexec)
- const char *filename;
- MEMREGION *env;
- const char *cmdlin;
- @@ -1070,6 +1337,7 @@
- MEMREGION **text; /* set to point to shared text region,
- if any */
- long *fp; /* prgflags for this file */
- + int isexec; /* this is an exec*() (overlay) */
- {
- FILEPTR *f;
- DEVDRV *dev;
- @@ -1077,6 +1345,7 @@
- BASEPAGE *b;
- long size, start;
- FILEHEAD fh;
- + SHTEXT *s;
-
- /* bug: this should be O_DENYW mode, not O_DENYNONE */
- /* we must use O_DENYNONE because of the desktop and because of the
- @@ -1105,30 +1374,45 @@
-
- if (fh.flag & F_SHTEXT) {
- TRACE(("loading shared text segment"));
- - shtext = get_text_seg(f, &fh, xp);
- - if (!shtext) {
- + s = get_text_seg(f, &fh, xp, 0L, isexec);
- + if (!s) {
- DEBUG(("load_region: unable to get shared text segment"));
- /* mint_errno set in get_text_seg */
- goto failed;
- }
- size = fh.fdata + fh.fbss;
- + shtext = s->text;
- } else {
- size = fh.ftext + fh.fdata + fh.fbss;
- shtext = 0;
- + s = 0;
- }
-
- - reg = create_base(cmdlin, env, fh.flag, size);
- + env->links++;
- + if (s && !shtext) {
- + reg = create_base(cmdlin, env, fh.flag, size,
- + isexec ? curproc : 0L, s, f, &fh, xp);
- + shtext = s->text;
- + } else {
- + if (shtext)
- + shtext->links++;
- + reg = create_base(cmdlin, env, fh.flag, size,
- + isexec ? curproc : 0L, 0L, 0L, 0L, 0L);
- + if (shtext)
- + shtext->links--;
- + }
- + env->links--;
- if (reg && size+1024L > reg->len) {
- DEBUG(("load_region: insufficient memory to load"));
- detach_region(curproc, reg);
- reg = 0;
- + mint_errno = ENSMEM;
- }
-
- if (reg == 0) {
- if (shtext) {
- detach_region(curproc, shtext);
- }
- - mint_errno = ENSMEM;
- goto failed;
- }
-
- @@ -1294,58 +1578,70 @@
- * process
- */
-
- -MEMREGION *
- -get_text_seg(f, fh, xp)
- +SHTEXT *
- +get_text_seg(f, fh, xp, s, noalloc)
- FILEPTR *f;
- FILEHEAD *fh;
- XATTR *xp;
- -{
- SHTEXT *s;
- + int noalloc;
- +{
- MEMREGION *m;
- long r;
- BASEPAGE b;
-
- - s = text_reg;
- + if (s) {
- + m = s->text;
- + } else {
- + s = text_reg;
-
- - while(s) {
- - if (s->f && samefile(&f->fc, &s->f->fc) &&
- - xp->mtime == s->mtime &&
- - xp->mdate == s->mdate)
- - {
- - m = s->text;
- + while(s) {
- + if (s->f && samefile(&f->fc, &s->f->fc) &&
- + xp->mtime == s->mtime &&
- + xp->mdate == s->mdate)
- + {
- + m = s->text;
- /* Kludge for unattached shared region */
- - if (m->links == 0xffff)
- - m->links = 0;
- + if (m->links == 0xffff)
- + m->links = 0;
-
- - if (attach_region(curproc, m)) {
- + if (attach_region(curproc, m)) {
- TRACE(("re-using shared text region %lx", m));
- - return m;
- - }
- - else {
- - mint_errno = ENSMEM;
- - return 0;
- + return s;
- + }
- + else {
- + mint_errno = ENSMEM;
- + return 0;
- + }
- }
- + s = s->next;
- }
- - s = s->next;
- - }
-
- /* hmmm, not found; OK, we'll have to create a new text region */
-
- - s = kmalloc(SIZEOF(SHTEXT));
- - if (!s) {
- - mint_errno = ENSMEM;
- - return 0;
- + s = kmalloc(SIZEOF(SHTEXT));
- + if (!s) {
- + mint_errno = ENSMEM;
- + return 0;
- + }
- + if (noalloc) {
- + s->f = 0;
- + s->text = 0;
- + return s;
- + }
- + m = 0;
- }
- - m = 0;
- + if (!m) {
- /* actually, I can't see why loading in TT RAM is ever undesireable,
- * since shared text programs should be very clean (and since only
- * the text segment is going in there). But better safe than sorry.
- */
- - if (fh->flag & F_ALTLOAD) {
- - m = addr2mem(alloc_region(alt, fh->ftext, PROT_P));
- + if (fh->flag & F_ALTLOAD) {
- + m = addr2mem(alloc_region(alt, fh->ftext, PROT_P));
- + }
- + if (!m)
- + m = addr2mem(alloc_region(core, fh->ftext, PROT_P));
- }
- - if (!m)
- - m = addr2mem(alloc_region(core, fh->ftext, PROT_P));
-
- if (!m) {
- kfree(s);
- @@ -1375,6 +1671,11 @@
-
- /* region has valid shared text data */
- m->mflags |= M_SHTEXT;
- +#if 1
- + if (xp->mode & 01000)
- +#endif
- +/* make it sticky (this should depend on the files mode!?) */
- + m->mflags |= M_SHTEXT_T;
-
- /*
- * KLUDGE: to make sure we always have up to date shared text
- @@ -1395,7 +1696,25 @@
- s->mdate = xp->mdate;
- text_reg = s;
- TRACE(("shared text region %lx created", m));
- - return m;
- + return s;
- +}
- +
- +/*
- + * function to just check for existence of a shared text region
- + * corresponding to file "f"
- + */
- +
- +MEMREGION *
- +find_text_seg(f)
- + FILEPTR *f;
- +{
- + SHTEXT *s;
- +
- + for (s = text_reg; s; s = s->next) {
- + if (s->f && samefile(&f->fc, &s->f->fc))
- + return s->text;
- + }
- + return 0;
- }
-
- /*
- Index: mem.h
- @@ -25,6 +25,8 @@
- #define M_MAP 0x0f /* and with this to pick out map */
-
- #define M_SHTEXT 0x10 /* region is a shared text region */
- +#define M_SHTEXT_T 0x20 /* `sticky bit' for shared text regions */
- +#define M_FSAVED 0x40 /* region is saved memory of a forked process */
- #define M_KEEP 0x0100 /* don't free on process termination */
-
- /* dummy type for virtual addresses */
- Index: proto.h
- @@ -154,6 +154,7 @@
- long ARGS_ON_STACK p_waitpid P_((int pid, int nohang, long *rusage));
- long ARGS_ON_STACK p_wait3 P_((int nohang, long *rusage));
- long ARGS_ON_STACK p_wait P_((void));
- +void ARGS_ON_STACK fork_restore P_((PROC *p, MEMREGION *savemem));
- long ARGS_ON_STACK p_vfork P_((void));
- long ARGS_ON_STACK p_fork P_((void));
-
- @@ -217,14 +218,16 @@
- MEMREGION *get_region P_((MMAP map, ulong size, int mode));
- void free_region P_((MEMREGION *reg));
- long shrink_region P_((MEMREGION *reg, ulong newsize));
- -long max_rsize P_((MMAP map));
- +long max_rsize P_((MMAP map, long needed));
- long tot_rsize P_((MMAP map, int flag));
- virtaddr alloc_region P_((MMAP map, ulong size, int mode));
- MEMREGION *create_env P_((const char *env, ulong flags));
- -MEMREGION *create_base P_((const char *cmd, MEMREGION *env, ulong flags, ulong prgsize));
- +MEMREGION *create_base P_((const char *cmd, MEMREGION *env, ulong flags, ulong prgsize,
- + PROC *execproc, SHTEXT *s, FILEPTR *f, FILEHEAD *fh, XATTR *xp));
- MEMREGION *load_region P_((const char *name, MEMREGION *env, const char *cmdlin, XATTR *x,
- - MEMREGION **text, long *fp));
- -MEMREGION *get_text_seg P_((FILEPTR *f, FILEHEAD *fh, XATTR *xp));
- + MEMREGION **text, long *fp, int isexec));
- +SHTEXT *get_text_seg P_((FILEPTR *f, FILEHEAD *fh, XATTR *xp, SHTEXT *s, int noalloc));
- +MEMREGION *find_text_seg P_((FILEPTR *f));
- long load_and_reloc P_((FILEPTR *f, FILEHEAD *fh, char *where, long start,
- long nbytes, BASEPAGE *base));
- void rts P_((void));
- --
- J"urgen Lock / nox@jelal.north.de / UUCP: ..!uunet!unido!uniol!jelal!nox
- ...ohne Gewehr
- PGP public key fingerprint = 8A 18 58 54 03 7B FC 12 1F 8B 63 C7 19 27 CF DA
-